package com.darwin.darwinDisplay
{
	import com.darwin.darwinBitmapEngine.core.MovieArrayNode;
	import com.darwin.darwinImage.jpg.JPEG32;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;

	[Event(name="darwin_draw_complete",type="com.darwin.darwinDisplay.DarBitmapMovieNodeEvent")]
	[Event(name="darwin_play_complete",type="com.darwin.darwinDisplay.DarBitmapMovieNodeEvent")]
	/**
	 * Darwin场景动画类
	 * <br/>此类只能添加到基于位图引擎的场景中，若想将dar资源作为UI直接添加在舞台上，请使用DarBitmapMovieClip类。
	 * @author jasonwluck,Roland
	 * 
	 */	
	public class DarBitmapMovieNode extends MovieArrayNode
	{
		/**
		 *	dar位图动画的透明边距(像素)
		 * <br>此边距用于避免位图滤镜后被截去一部分
		 * <br><b>边距越大，dar占用内存越大，请自行酌情调整</b>
		 */
		public static var transMargins:int = 5;
		private var _sourceClass:Class;
		private var _sourceDisplayObject:DisplayObject;
		private var _sourceDar:DarBitmapData;
		
		//上中下 三层位图		
		private var _upBitmap:Bitmap;
		private var _midBitmap:Bitmap;
		private var _downBitmap:Bitmap;
		//上中下 三层位图数据
		private var _upBitmapData:BitmapData;
		private var _midBitmapData:BitmapData;
		private var _downBitmapData:BitmapData;
		private var _finBitmapData:BitmapData;//最终合成的位图

		//上中下 三层位图播放信息
		private var _upFrameMes:Array;
		private var _midFrameMes:Array;
		private var _downFrameMes:Array;
		//用于监测加载了几层位图数据
		private var _totalLayer:int;
		//每帧的位图
		private var _frames:Array;
		private var _framesOffsetList:Array;
		private var _isComplete:Boolean;
		
		private var _isMirror:Boolean;
		
		private var _offsetPoint:Point;

		/**
		 * darwinBitmapMovieClip管理器 
		 */		
		private var _darwinBitmapManager:DarBitmapManager;
		
		private var _completeCallBack:Function;
		
		/**
		 *	 实例化一个Darwin场景动画类
		 * @param source 动画源文件 DarwinBitmapData/Class 
		 * @param completeCallBack 完成后的回调
		 * @param frames 已经绘制完成的位图帧序列，如果传此参数，则将直接播放frames中的数据，而不会重新绘制source
		 * @param offsetPoint 和frames向对应的偏移量，必须和frames一起传入，如果传此参数，则将使用此点作为偏移量，而不会通过source计算
		 * @param isMirror 是否为镜像
		 * @param framesoffsetList
		 */
		public function DarBitmapMovieNode(source:* = null,completeCallBack:Function = null,frames:Array = null,offsetPoint:Point = null,isMirror:Boolean = false,framesoffsetList:Array = null)
		{
			initDarMovieNode(source,completeCallBack,frames,offsetPoint,isMirror,framesoffsetList);
		}
		
		protected function initDarMovieNode(source:* = null,completeCallBack:Function = null,frames:Array = null,offsetPoint:Point = null,isMirror:Boolean = false,framesoffsetList:Array = null):void
		{
			if(!source){return;};
			_completeCallBack = completeCallBack;
			_darwinBitmapManager = DarBitmapManager.getInstance();
			_isMirror = isMirror;
			this.frameRate = 8;
			
			setSource(source);
			if(frames != null)
			{
				drawCompFn(frames,offsetPoint,framesoffsetList);
			}else{
				draw();
			}
		}
		
		
		private function setSource(source:*):void
		{
			if(source is Class)
			{
				_sourceClass = source;
			}else if(source is DisplayObject)
			{
				_sourceDisplayObject = source;
			}else if(source is DarBitmapData)
			{
				_sourceDar = source;
			}else
			{
				throw (new Error("DarwinBitmapMovieClip 源数据无效"));
			}
			_darwinBitmapManager.addQuote(source);//引用计数加1
		}
		
		private function draw():void
		{
			if(_sourceClass)
			{
				drawClass(source);
			}else if(_sourceDisplayObject)
			{
				drawDisplayObject(source);
			}else if(_sourceDar)
			{
				drawDarwinBitmapData(_sourceDar);
			}
		}
		
		private function drawClass(sourceClass:Class):void
		{
			_darwinBitmapManager.drawClass(sourceClass,drawCompFn);
		}

		
		private function drawDisplayObject(sourceDisplayObject:DisplayObject):void
		{
			
		}
		
		private function drawDarwinBitmapData(sourceDarwinBitmapData:DarBitmapData):void
		{
			_darwinBitmapManager.drawDar(sourceDarwinBitmapData,initDarwinBitmap);
		}
		
		private function drawCompFn(bitmapDataArray:Array,offsetPoint:Point,framesOffsetList:Array = null):void
		{
			bitmapData = bitmapDataArray[0];
			_offsetPoint = offsetPoint;
			_framesOffsetList = framesOffsetList;
			initMovieNode(bitmapDataArray,framesOffsetList);
			if(_completeCallBack != null)
			{
				_completeCallBack();
			}
			dispatchEvent(new DarBitmapMovieNodeEvent(DarBitmapMovieNodeEvent.DARWIN_DRAW_COMPLETE));
			_isComplete = true;
		}
		
		override public function render():void
		{
			var $lastFrame:int = currentFrame;
			super.render();
			if($lastFrame != currentFrame && currentFrame==totalFrames-1)
			{
				if(totalFrames>1)
				{
					renderNotify = true;//标记渲染完成通知
				}
			}
		}
		
		override public function exeRenderNotify():void
		{
			if(!isStop)
			{
				super.exeRenderNotify();
				dispatchEvent(new DarBitmapMovieNodeEvent(DarBitmapMovieNodeEvent.DARWIN_PLAY_COMPLETE));
			}
		}
		
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
		{
			super.addEventListener(type, listener, useCapture, priority, useWeakReference);
			if(type == DarBitmapMovieNodeEvent.DARWIN_DRAW_COMPLETE)
			{
				if(_isComplete)
				{
					dispatchEvent(new DarBitmapMovieNodeEvent(DarBitmapMovieNodeEvent.DARWIN_DRAW_COMPLETE));
				}
			}
		}
		
		private var _upLoop:int = 0;
		private var _midLoop:int = 0;
		private var _downLoop:int = 0;

		private var _totalframeNum:int;
		
		private function drawFrame(index:int,total:int):void
		{
			var frame:int = index-1;
			var gotoFrame:int;
			if(_frames==null || _frames[frame] == null)
			{
				if(_upBitmap)
				{
					if(frame <= _upFrameMes.length)
					{
						var upFrameArr:Array = _upFrameMes[frame];
						if(upFrameArr[7] != 0)
						{
							if(_upLoop < upFrameArr[8])
							{
								gotoFrame = upFrameArr[7];
								index = gotoFrame;
								frame = index - 1;
								upFrameArr = _upFrameMes[frame];
								_upLoop ++;
							}else
							{
								_upLoop = 0;
							}
							
						}
						refresh(upFrameArr,_upBitmap,_upBitmapData);
					}
				}
				
				if(_midBitmap)
				{
					if(frame <= _midFrameMes.length)
					{
						var midFrameArr:Array = _midFrameMes[frame];
						if(midFrameArr[7] != 0)
						{
							if(_midLoop < midFrameArr[8])
							{
								gotoFrame = midFrameArr[7];
								index = gotoFrame;
								frame = index - 1;
								midFrameArr = _midFrameMes[frame];
								_midLoop ++;
							}else
							{
								_midLoop = 0;
							}
							
						}
						refresh(midFrameArr,_midBitmap,_midBitmapData);
					}
				}
				
				if(_downBitmap)
				{
					if(frame <= _downFrameMes.length)
					{
						var downFrameArr:Array = _downFrameMes[frame];
						if(downFrameArr[7] != 0)
						{
							if(_downLoop < downFrameArr[8])
							{
								gotoFrame = downFrameArr[7];
								index = gotoFrame;
								frame = index - 1;
								downFrameArr = _downFrameMes[frame];
								_downLoop ++;
							}else
							{
								_downLoop = 0;
							}
							
						}
						refresh(downFrameArr,_downBitmap,_downBitmapData);
					}
				}
			}
		
			synthesis(index);
		}
		
		/**
		 *	清理第一遍绘制所需资源 
		 * 
		 */
		private function clearPreSource():void
		{
			if(_upBitmap)_upBitmap.bitmapData.dispose();
			if(_midBitmap)_midBitmap.bitmapData.dispose();
			if(_downBitmap)_downBitmap.bitmapData.dispose();

			_upBitmap = null;
			_midBitmap = null;
			_downBitmap = null;
		}
		
		/**
		 * 合成三个层次到画布
		 */
		private function synthesis(index:int):void
		{
			//合成到画布
			if(_finBitmapData){
				if(_frames == null)
				{
					_frames = [];
				}
				if(_framesOffsetList == null)
				{
					_framesOffsetList = [];
				}
				if(_frames[index-1] == null)
				{
					var destPoint:Point = new Point();
					if(_upBitmap)_finBitmapData.copyPixels(_upBitmap.bitmapData,_upBitmap.bitmapData.rect,destPoint);
					if(_midBitmap)_finBitmapData.copyPixels(_midBitmap.bitmapData,_midBitmap.bitmapData.rect,destPoint);
					if(_downBitmap)_finBitmapData.copyPixels(_downBitmap.bitmapData,_downBitmap.bitmapData.rect,destPoint);
					var offsetRect:Rectangle = _finBitmapData.getColorBoundsRect(0xff000000,0,false);
					//留出透明边距
					offsetRect.x = offsetRect.x - transMargins;
					offsetRect.y = offsetRect.y - transMargins;
					offsetRect.width = offsetRect.width + transMargins*2;
					offsetRect.height = offsetRect.height + transMargins*2;
					//如果是空帧，申请一个高宽各为1的位图
					if(offsetRect.width==0)offsetRect.width = 1;
					if(offsetRect.height==0)offsetRect.height = 1;
					var frameBitmapData:BitmapData = new BitmapData(offsetRect.width,offsetRect.height,true,0);
					frameBitmapData.copyPixels(_finBitmapData,offsetRect,destPoint);
					_frames[index-1] = frameBitmapData;
					_framesOffsetList[index-1] = offsetRect;
				}
			}
		}
		
		/**
		 * 刷新各个层次位图 
		 * @param frameMes
		 * @param targetBitmap
		 * @param copyBitmapData
		 * 
		 */		
		private function refresh(frameMes:Array,targetBitmap:Bitmap,copyBitmapData:BitmapData):void
		{
			var clearTag:Boolean = frameMes[6];
			var $rect:Rectangle = new Rectangle(frameMes[0],frameMes[1],frameMes[2],frameMes[3]);
			var startPoint:Point = new Point(frameMes[4],frameMes[5]);
			if(clearTag)
			{
				targetBitmap.bitmapData = new BitmapData(targetBitmap.width,targetBitmap.height,true,0);
			}
			targetBitmap.bitmapData.copyPixels(copyBitmapData,$rect,startPoint);
		}
		
		/**
		 * 初始化动画数据
		 * 
		 */		
		private function initDarwinBitmap(bitmapDataArray:Array = null,offsetPoint:Point = null,framesOffsetList:Array = null):void
		{
			if(bitmapDataArray && offsetPoint)
			{
				startPlay(bitmapDataArray,offsetPoint,framesOffsetList);
			}else{
				var maxRect:Array = [];
				var upFrame:int = 0;
				var midFrame:int = 0;
				var downFrame:int = 0;
				var bigCon:Sprite = new Sprite();
				var container:Sprite = new Sprite();
				_totalframeNum = 0;
				bigCon.addChild(container);
				if(_sourceDar.darwinUp)
				{
					_upFrameMes = _sourceDar.darwinUp["frameMes"];
					upFrame = _upFrameMes.length;
				}
				if(_sourceDar.darwinMid)
				{
					_midFrameMes = _sourceDar.darwinMid["frameMes"];
					midFrame = _midFrameMes.length;
				}
				if(_sourceDar.darwinDown)
				{
					_downFrameMes = _sourceDar.darwinDown["frameMes"];
					downFrame = _downFrameMes.length;
				}
				_totalframeNum = Math.max(upFrame,midFrame,downFrame);
				
				
				if(_sourceDar.darwinUp)
				{
					_upBitmap = new Bitmap();
					var upOffSet:Array = _sourceDar.darwinUp["offSet"];
					_upBitmap.x = upOffSet[0];
					_upBitmap.y = upOffSet[1];
					maxRect = _sourceDar.darwinUp["maxRect"];
					_upBitmap.bitmapData = new BitmapData(maxRect[0] + transMargins*2,maxRect[1] + transMargins*2,true,0);
					container.addChild(_upBitmap);
				}
				
				if(_sourceDar.darwinMid)
				{
					_midBitmap = new Bitmap();
					var midOffSet:Array = _sourceDar.darwinMid["offSet"];
					_midBitmap.x = midOffSet[0];
					_midBitmap.y = midOffSet[1];
					maxRect = _sourceDar.darwinMid["maxRect"];
					_midBitmap.bitmapData = new BitmapData(maxRect[0] + transMargins*2,maxRect[1] + transMargins*2,true,0);
					container.addChild(_midBitmap);
				}
				
				if(_sourceDar.darwinDown)
				{
					_downBitmap = new Bitmap();
					var downOffSet:Array = _sourceDar.darwinDown["offSet"];
					_downBitmap.x = downOffSet[0];
					_downBitmap.y = downOffSet[1];
					maxRect = _sourceDar.darwinDown["maxRect"];
					_downBitmap.bitmapData = new BitmapData(maxRect[0] + transMargins*2,maxRect[1] + transMargins*2,true,0);
					container.addChild(_downBitmap);
				}
				
				if(_sourceDar.darwinUp || _sourceDar.darwinMid || _sourceDar.darwinDown)
				{
					var $bitmapRect:Rectangle = container.getRect(bigCon);
					_offsetPoint = new Point($bitmapRect.x,$bitmapRect.y);
					_finBitmapData = new BitmapData($bitmapRect.width,$bitmapRect.height,true,0);
					//rect = _finBitmapData.rect;
					bitmapData = _finBitmapData;
				}
				
				if(_sourceDar.darwinUp)
				{
					decodeBitmapDataByteArray("UP",_sourceDar.darwinUp["bitmapDataByteArray"]);				
				}
				if(_sourceDar.darwinMid)
				{
					decodeBitmapDataByteArray("MID",_sourceDar.darwinMid["bitmapDataByteArray"]);				
				}
				if(_sourceDar.darwinDown)
				{
					decodeBitmapDataByteArray("DOWN",_sourceDar.darwinDown["bitmapDataByteArray"]);				
				}

			}

			


		}
		
		
		/**
		 *	原始素材偏移量
		 * @return 
		 * 
		 */
		override public function get offsetPoint():Point
		{
			return _offsetPoint;
		}
		
		/**
		 * 解析位图数据 
		 * @param name
		 * @param bitmapDataByteArray
		 * 
		 */		
		private function decodeBitmapDataByteArray(name:String,bitmapDataByteArray:*):void
		{
			if(bitmapDataByteArray is Bitmap)
			{
				dealBitmapData(name,bitmapDataByteArray);
			}else if(bitmapDataByteArray is ByteArray)
			{
				var jpeg32:JPEG32 = new JPEG32();
				jpeg32.addEventListener(Event.COMPLETE,onJpegDecodeComplete);
				jpeg32.decode(bitmapDataByteArray);
				function onJpegDecodeComplete(event:Event):void
				{
					jpeg32.removeEventListener(Event.COMPLETE,onJpegDecodeComplete);
					var bitmap:Bitmap = new Bitmap(jpeg32.bitmapData);
					dealBitmapData(name,bitmap);
				}
			}
		}
		
		private function dealBitmapData(name:String,bitmap:Bitmap):void
		{
			switch(name)
			{
				case "UP":
					_upBitmapData = bitmap.bitmapData;
					_sourceDar.darwinUp["bitmapDataByteArray"] = bitmap;
					_totalLayer ++;
				break;
				case "MID":
					_midBitmapData = bitmap.bitmapData;
					_sourceDar.darwinMid["bitmapDataByteArray"] = bitmap;
					_totalLayer ++;
				break;
				case "DOWN":
					_downBitmapData = bitmap.bitmapData;
					_sourceDar.darwinDown["bitmapDataByteArray"] = bitmap;
					_totalLayer ++;
				break;
				default:
				break;
			}
			
			// 所有位图数据都已准备好
			if(_totalLayer == _sourceDar.totalLayer)
			{
				startPlay();
			}
		}
		
		/**
		 * 所有数据准备完毕，开始播放动画 
		 * 
		 */		
		private function startPlay(frames:Array = null,offsetPoint:Point = null,framesOffsetList:Array = null):void
		{
			if(frames && offsetPoint)
			{
				_frames = frames;
				_offsetPoint = offsetPoint;
				_framesOffsetList = framesOffsetList;
				bitmapData = _frames[0];
			}else{
				for (var i:int = 1; i <= _totalframeNum; i++) 
				{
					drawFrame(i,_totalframeNum);
				}
			}

			
			clearPreSource();
			
			initMovieNode(_frames,_framesOffsetList);
			
			_darwinBitmapManager.darBitmapMovieClipComplete(source,_frames,_offsetPoint,_framesOffsetList);
			
			if(_completeCallBack != null){_completeCallBack();}
			dispatchEvent(new DarBitmapMovieNodeEvent(DarBitmapMovieNodeEvent.DARWIN_DRAW_COMPLETE));
			
			_isComplete = true;
		}

		
		/**
		 * 销毁该动画 
		 * 
		 */		
		override public function destroy():void
		{
			super.destroy();
			if(_darwinBitmapManager){
				_darwinBitmapManager.destroy(source);
			}
			_sourceDar = null;
			_sourceClass = null;
			_sourceDisplayObject = null;
 		}

		/**
		 *	位图碰撞检测 
		 * @param x
		 * @param y
		 * @param alphaThreshold
		 * @return 
		 * 
		 */
		override public function hitTest(x:Number, y:Number,alphaThreshold:uint = 0x00):Boolean
		{
			var $hitTestPoint:Point = new Point(x,y);
			if(hitTestPointBitmapData(bitmapData,$hitTestPoint,alphaThreshold))
			{
				return true;
			}
			return false;
		}
		
		protected function hitTestPointBitmapData(bitmapData:BitmapData,point:Point,alphaThreshold:uint = 0x00):Boolean
		{
			var p:Point = point;
			if(bitmapData != null)
			{
				var u:uint = bitmapData.getPixel32(p.x,p.y);
				var rgb:uint = u & 0x00FFFFFF;
				var a:uint = u >>> 24;
				if(a > alphaThreshold)
				{
					return true;
				}
			}
			return false;
		} 
		
		override public function get bitmapData():BitmapData
		{
			return super.bitmapData;
		}

		/**
		 *  位图是否准备完成
		 */
		public function get isComplete():Boolean
		{
			return _isComplete;
		}

		/**
		 * @private
		 */
		public function set isComplete(value:Boolean):void
		{
			_isComplete = value;
		}

		private var _mirror:DarBitmapMovieNode;
		/**
		 *	返回一份此动画的镜像，动画对象中每一帧都和原图中的对称
		 * @return 
		 * 
		 */
		public function get mirror():DarBitmapMovieNode
		{
			if(bitmapDataList==null) throw new Error("请等待dar动画绘制完成再取镜像");
			if(_mirror == null)
			{
				var $mirrorFrames:Array = DarBitmapManager.getInstance().drawMirror(source,bitmapDataList,_isMirror);
				var $mirrorOffset:Point = new Point(-(rect.width + offsetPoint.x),offsetPoint.y);
				var $mirrorFramesOffsetList:Array;
				if(_framesOffsetList)
				{
					$mirrorFramesOffsetList = [];
					for (var i:int = 0; i < _framesOffsetList.length; i++) 
					{
						var $offsetRect:Rectangle = (_framesOffsetList[i] as Rectangle).clone();
						$offsetRect.x = rect.width -($offsetRect.width + $offsetRect.x);
						$mirrorFramesOffsetList.push($offsetRect);
					}
				}
				_mirror = new DarBitmapMovieNode(source,null,$mirrorFrames,$mirrorOffset,!_isMirror,$mirrorFramesOffsetList);
			}
			return _mirror;
		}
		
		public function get source():*
		{
			if(_sourceDar)
			{
				return _sourceDar;	
			}
			else if(_sourceClass)
			{
				return _sourceClass;
			}
			else if(_sourceDisplayObject)
			{
				return _sourceDisplayObject;
			}
			return null;
		}

		/**
		 *	此动画对象是否为镜像 
		 */
		public function get isMirror():Boolean
		{
			return _isMirror;
		}

	}
}